package com.kaibes.web.response;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.ResponseEntity.BodyBuilder;
import org.springframework.http.server.ServerHttpResponse;

public class ResponseFactory {
    
	public static String MESSAGE = "x-api-message";
	public static String CODE = "x-api-code";
	public static String REDIRECT = "x-api-redirect";
    
    public static String urlEncode(String message) {
        try {
            return URLEncoder.encode(message, "utf-8");
        } catch (UnsupportedEncodingException e) {
            return message;
        }
    }
    
    public static String getMessage(ServerHttpResponse response) {
    	return response.getHeaders().getFirst(MESSAGE);
    }
    public static String getCode(ServerHttpResponse response) {
    	return response.getHeaders().getFirst(CODE);
    }
    public static String getRedirect(ServerHttpResponse response) {
    	return response.getHeaders().getFirst(REDIRECT);
    }
    
    // =============
    public static <T> ResponseEntity<T> status(int status) {
        return status(status, null, null, null);
    }
    public static <T> ResponseEntity<T> status(int status, String message) {
        return status(status, null, null, message);
    }
    public static <T> ResponseEntity<T> status(int status, String code, String message) {
        return status(status, code, null, message);
    }
    public static <T> ResponseEntity<T> status(int status, String code, String uri, String message) {
    	return body(null, status, code, uri, message);
    }
    
    public static <T> ResponseEntity<T> body(T body, int status) {
        return body(body, status, null);
    }
    public static <T> ResponseEntity<T> body(T body, int status, String message) {
        return body(body, status, null, message);
    }
    public static <T> ResponseEntity<T> body(T body, int status, String code, String message) {
        return body(body, status, code, null, message);
    }
    public static <T> ResponseEntity<T> body(T body, int status, String code, String uri, String message) {
        BodyBuilder builder =  ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON);
        if (code != null) {
            builder.header(CODE, code);
        }
        if (uri != null) {
            builder.header(REDIRECT, uri);
        }
        if (message != null) {
            builder.header(MESSAGE, urlEncode(message));
        }
        if (body != null) {
        	return builder.body(body);
        } else {
        	return builder.build();
        }
    }

    
    // ========== 200
    public static <T> ResponseEntity<T> ok() {
        return ok(null, null, null);
    }
    public static <T> ResponseEntity<T> ok(String message) {
        return ok(null, null, message);
    }
    public static <T> ResponseEntity<T> ok(T body) {
        return ok(body, null, null);
    }
    public static <T> ResponseEntity<T> ok(T body, String message) {
        return ok(body, null, message);
    }
    public static <T> ResponseEntity<T> ok(T body, String code, String message) {
        BodyBuilder builder = ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON);
        if (code != null) {
            builder.header(CODE, code);
        }
        if (message != null) {
            builder.header(MESSAGE, urlEncode(message));
        }
        if (body != null) {
            return builder.body(body);
        } else {
            return builder.build();
        }
    }
    
    public static <T> ResponseEntity<T> okMove(String uri, String message) {
        return ResponseEntity.ok().header(MESSAGE, urlEncode(message)).header(REDIRECT, uri).build();
    }

    public static <T> ResponseEntity<T> created(URI location) {
        return ResponseEntity.created(location).build();
    }
    public static <T> ResponseEntity<T> created(URI location, String message) {
        return ResponseEntity.created(location).header(MESSAGE, urlEncode(message)).build();
    }

    public static <T> ResponseEntity<T> noContent() {
        return ResponseEntity.noContent().build();
    }
    public static <T> ResponseEntity<T> noContent(String message) {
        return ResponseEntity.noContent().header(MESSAGE, urlEncode(message)).build();
    }
    
    // ========== 300
    public static <T> ResponseEntity<T> multiple(String uri) {
        return ResponseEntity.status(HttpStatus.MULTIPLE_CHOICES).header(REDIRECT, uri).build();
    }
    public static <T> ResponseEntity<T> moved(String uri) {
        return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).header(REDIRECT, uri).build();
    }
    public static <T> ResponseEntity<T> moved(String uri, String message) {
        return ResponseEntity.status(HttpStatus.MOVED_PERMANENTLY).header(MESSAGE, urlEncode(message)).header(REDIRECT, uri).build();
    }
    public static <T> ResponseEntity<T> found(String uri) {
        return ResponseEntity.status(HttpStatus.FOUND).header(REDIRECT, uri).build();
    }
    public static <T> ResponseEntity<T> found(String uri, String message) {
        return ResponseEntity.status(HttpStatus.FOUND).header(MESSAGE, urlEncode(message)).header(REDIRECT, uri).build();
    }

    // ========== 400
    public static <T> ResponseEntity<T> badRequest() {
        return ResponseEntity.badRequest().build();
    }
    public static <T> ResponseEntity<T> badRequest(T body) {
        return ResponseEntity.badRequest().body(body);
    }
    public static <T> ResponseEntity<T> badRequest(T body, String message) {
        return ResponseEntity.badRequest().header(MESSAGE, urlEncode(message)).body(body);
    }
    public static <T> ResponseEntity<T> badRequest(String message) {
        return ResponseEntity.badRequest().header(MESSAGE, urlEncode(message)).build();
    }
    public static <T> ResponseEntity<T> badRequest(String code, String message) {
    	return ResponseEntity.badRequest().header(CODE, code).header(MESSAGE, urlEncode(message)).build();
    }
    public static <T> ResponseEntity<T> unauthorized() {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
    }
    public static <T> ResponseEntity<T> unauthorized(String message) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).header(MESSAGE, urlEncode(message)).build();
    }
    public static <T> ResponseEntity<T> unauthorized(String message, String uri) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).header(MESSAGE, urlEncode(message)).header(REDIRECT, uri).build();
    }

    public static <T> ResponseEntity<T> notFound() {
        return ResponseEntity.notFound().build();
    }
    public static <T> ResponseEntity<T> notFound(String message) {
        return ResponseEntity.notFound().header(MESSAGE, urlEncode(message)).build();
    }

    public static <T> ResponseEntity<T> unprocessableEntity() {
        return ResponseEntity.unprocessableEntity().build();
    }
    public static <T> ResponseEntity<T> unprocessableEntity(String message) {
        return ResponseEntity.unprocessableEntity().header(MESSAGE, urlEncode(message)).build();
    }

    public static <T> ResponseEntity<T> conflict() {
        return ResponseEntity.status(HttpStatus.CONFLICT).build();
    }
    public static <T> ResponseEntity<T> conflict(String message) {
        return ResponseEntity.status(HttpStatus.CONFLICT).header(MESSAGE, urlEncode(message)).build();
    }

 // =============POST
    public static <T> ResponseEntity<T> postSuccess() {
        return noContent();
    }

    public static <T> ResponseEntity<T> postFailure() {
        return badRequest();
    }
    
    public static <T> ResponseEntity<T> postFailure(T body) {
        return badRequest(body);
    }

    public static <T> ResponseEntity<T> postSuccess(T body) {
        return ok(body);
    }
    
    public static <T> ResponseEntity<T> postSuccess(String message) {
        return ok(message);
    }
    
    public static <T> ResponseEntity<T> postSuccess(T body, String message) {
        return ok(body, message);
    }
    
    public static <T> ResponseEntity<T> postSuccess(T body, String code, String message) {
    	return ok(body, code, message);
    }
    
    public static <T> ResponseEntity<T> postFailure(T body, String message) {
    	return badRequest(body, message);
    }
    
    public static <T> ResponseEntity<T> postFailure(String message) {
        return badRequest(message);
    }
    
    public static <T> ResponseEntity<T> postFailure(String code, String message) {
    	return badRequest(code, message);
    }

    public static <T> ResponseEntity<T> post(boolean flag) {
        if (flag) {
            return postSuccess();
        } else {
            return postFailure();
        }
    }
    
    public static <T> ResponseEntity<T> post(boolean flag, String successMessage, String failureMessage) {
        if (flag) {
            return postSuccess(successMessage);
        } else {
            return postFailure(failureMessage);
        }
    }
    
    public static <T> ResponseEntity<T> post(T result, String successMessage, String failureMessage) {
        if (result != null) {
            return postSuccess(result, successMessage);
        } else {
            return postFailure(failureMessage);
        }
    }
    
    public static <T> ResponseEntity<T> post(boolean flag, T result, String successMessage, String failureMessage) {
        if (flag) {
            return postSuccess(result, successMessage);
        } else {
            return postFailure(failureMessage);
        }
    }
    
    // ================DELETE
    public static <T> ResponseEntity<T> deleteSuccess() {
        return noContent();
    }
    public static <T> ResponseEntity<T> deleteFailure() {
        return badRequest();
    }
    public static <T> ResponseEntity<T> deleteSuccess(String message) {
        return ok(message);
    }
    public static <T> ResponseEntity<T> deleteFailure(String message) {
        return badRequest(message);
    }
    
    public static <T> ResponseEntity<T> delete(boolean flag) {
        if (flag) {
            return deleteSuccess();
        } else {
            return deleteFailure();
        }
    }
    public static <T> ResponseEntity<T> delete(long count) {
        return delete(count > 0);
    }
    public static <T> ResponseEntity<T> delete(boolean flag, String successMessage, String failureMessage) {
        if (flag) {
            return deleteSuccess(successMessage);
        } else {
            return deleteFailure(failureMessage);
        }
    }
    public static <T> ResponseEntity<T> delete(long count, String successMessage, String failureMessage) {
        return delete(count > 0, successMessage, failureMessage);
    }
    
    // ================PUT
    public static <T> ResponseEntity<T> putSuccess() {
        return noContent();
    }
    public static <T> ResponseEntity<T> putFailure() {
        return badRequest();
    }
    public static <T> ResponseEntity<T> putSuccess(String message) {
        return ok(message);
    }
    public static <T> ResponseEntity<T> putFailure(String message) {
        return badRequest(message);
    }
    public static <T> ResponseEntity<T> putSuccess(T data) {
        return ok(data);
    }
    public static <T> ResponseEntity<T> putSuccess(T data, String message) {
        return ok(data, message);
    }
    
    public static <T> ResponseEntity<T> put(boolean flag) {
        if (flag) {
            return putSuccess();
        } else {
            return putFailure();
        }
    }
    public static <T> ResponseEntity<T> put(long count) {
        return put(count > 0);
    }
    public static <T> ResponseEntity<T> put(boolean flag, String successMessage, String failureMessage) {
        if (flag) {
            return putSuccess(successMessage);
        } else {
            return putFailure(failureMessage);
        }
    }
    public static <T> ResponseEntity<T> put(long count, String successMessage, String failureMessage) {
        return put(count > 0, successMessage, failureMessage);
    }
    
    // ================GET
    public static <T> ResponseEntity<T> getSuccess(T data) {
        return ok(data);
    }
    public static  <T> ResponseEntity<T> getFailure(T data) {
        return badRequest(data);
    }
    public static  <T> ResponseEntity<T> getFailure() {
        return notFound();
    }
    
    public static <T> ResponseEntity<T> getSuccess(T data, String message) {
        return ok(data, message);
    }
    public static  <T> ResponseEntity<T> getFailure(String message) {
        return badRequest(message);
    }
    
    public static  <T> ResponseEntity<T> get(T data) {
        if (data == null) {
            return getFailure();
        } else {
            return getSuccess(data);
        }
    }
    public static  <T> ResponseEntity<T> get(T data, String successMessage, String failureMessage) {
        if (data == null) {
            return getFailure(failureMessage);
        } else {
            return getSuccess(data, successMessage);
        }
    }
}
